﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
using System.Diagnostics;
using System.Globalization;
using System.Threading;
using System.Runtime.InteropServices;

namespace MDSD.OfficeView
{
    public partial class OfficeViewer : Control
    {  
        private Excel.Application application;
        private Process process;
        public IntPtr excelHandle;
        private bool initialized = false;
        private Excel.Workbooks workbooks;
        private Excel.Workbook workbook;
        private CultureInfo threadCulture;

        private const int SWP_FRAMECHANGED = 0x0020;
        private const int SWP_DRAWFRAME = 0x20;
        private const int SWP_NOMOVE = 0x2;
        private const int SWP_NOSIZE = 0x1;
        private const int SWP_NOZORDER = 0x4;
        private const int GWL_STYLE = (-16);
        private const int WS_CAPTION = 0xC00000;
        private const int WS_THICKFRAME = 0x40000;
        private const int WS_SIZEBOX = WS_THICKFRAME;
        private const int SWP_NOACTIVATE = 0x0010;

        [DllImport("user32.dll", SetLastError = true)]
        private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

        [DllImport("user32.dll", SetLastError = true)]
        public static extern int GetWindowLong(IntPtr hWnd, int nIndex);

        [DllImport("user32.dll")]
        public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

        [DllImport("User32", SetLastError = true)]
        public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);

        [DllImport("user32.dll", SetLastError = true)]
        public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);

        public bool Saved
        {
            get { return workbook.Saved; }
        }

        public Excel.Application Application
        {
            get { return application; }
        }

        public OfficeViewer()
        {
            this.Resize += new EventHandler(ExcelViewer_Resize);
        }

        public void Init()
        {
            threadCulture = Thread.CurrentThread.CurrentCulture;
            Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");

            application = new Excel.Application();
            application.WindowState = Excel.XlWindowState.xlNormal;
            application.Visible = true;

            excelHandle = new IntPtr(application.Hwnd);
            SetParent(excelHandle, this.Handle);
            int lngStyle = GetWindowLong(excelHandle, GWL_STYLE);
            lngStyle = lngStyle ^ WS_CAPTION;
            lngStyle = lngStyle ^ WS_SIZEBOX;
            lngStyle = lngStyle ^ WS_SIZEBOX;
            SetWindowLong(excelHandle, GWL_STYLE, lngStyle);
            SetWindowPos(excelHandle, new IntPtr(0), 0, 0, this.Width, this.Height, SWP_FRAMECHANGED);
            int pid = 0;
            GetWindowThreadProcessId(excelHandle, out pid);
            process = Process.GetProcessById(pid);
            initialized = true;
        }

        public void OpenFile(string filename)
        {
            if (!initialized)
                Init();
            workbooks = application.Workbooks;
            workbook = workbooks.Open(filename);
        }

        public void CloseExcel()
        {
            closeExcel();
        }

        private void closeExcel()
        {
            try
            {
                if (workbook != null)
                {
                    workbook.Close(false);
                    Marshal.ReleaseComObject(workbooks);
                    Marshal.ReleaseComObject(workbook);
                }
                if (application != null)
                {
                    application.Quit();
                    Marshal.ReleaseComObject(application);
                    process.WaitForExit();
                }
            }
            catch (Exception e) { }
            finally
            {
                workbook = null;
                workbooks = null;
                application = null;
                if (process != null && !process.HasExited)
                    process.Kill();
                Thread.CurrentThread.CurrentCulture = threadCulture;
                initialized = false;
            }
        }

        public void KillExcel()
        {
            if (process != null)
                process.Kill();
        }

        public void SaveActiveWorkbook()
        {
            workbook.Save();
        }

        public void SaveActiveWorkbookAs(string filename)
        {
            workbook.SaveAs(filename);
        }

        public void SaveCopyOfActiveWorksheetAs(string filename)
        {
            workbook.SaveCopyAs(filename);
        }

        private void ExcelViewer_Resize(object sender, EventArgs e)
        {
            if (excelHandle != IntPtr.Zero)
            {
                SetWindowPos(excelHandle, new IntPtr(0), 0, 0, this.Width, this.Height, SWP_NOACTIVATE);
            }
        }

        protected override void OnHandleDestroyed(EventArgs e)
        {
            CloseExcel();
            base.OnHandleDestroyed(e);
        }
    }
}
